﻿using DeHeng_Mes.Constant;
using DeHeng_Mes.Dao;
using DeHeng_Mes.Model.OrderSingleton;
using DeHeng_Mes.Model.Table;
using DeHeng_Mes.Utils;
using NPOI.SS.Formula.Functions;
using S7.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace DeHeng_Mes.PlcService
{
    public class VerificationService
    {
        #region 成员实例
        OrderDao orderDao = new OrderDao();
        #endregion

        public byte CodeVerification(string station, string code, string operationId)
        {

          
            /*// 初始化报警码
            List<int> errorCodes = new List<int>();

            // 初始化NG状态列表
            List<bool> NgStatus = new List<bool>();*/

            // 初始化NG校验(有出站记录)
            bool ngStationIsGoOut = false;

            // 初始化返回状态
            byte returnByte = 1;

            try
            {
                
                // 格式校验
                bool isOk = CodeIsOk(code ,station);

                // 重码校验
                bool isSave = CodeIsSave(code, station);

                // 产量校验
                bool productionIsOk = OrderProductionIsOk(station);

                // 跳工序校验
                bool operationIsOk = OperationIsOk(code, station, operationId);

                if (station.Contains("_NG"))
                {
                    ngStationIsGoOut = !orderDao.NgStationIsSave(code, station, "1");
                }

                if (isOk || isSave || productionIsOk || ngStationIsGoOut || operationIsOk)
                {
                    if (productionIsOk)
                    {
                        return 7;
                    }

                    if (isOk)
                    {
                        return 5;
                    }

                    if (isSave)
                    {
                        return 6;
                    }

                    if (ngStationIsGoOut)
                    {
                        return 8;
                    }

                    if (operationIsOk)
                    {
                        return 9;
                    }
                }
            }
            catch (Exception ex)
            {
                Tools.ProduceLogTextError($"[{station}]触发校验失败，原因是[{ex.Message}]");

                return returnByte = 0;
            }
            return returnByte;
        }

        /// <summary>
        /// 检测重码
        /// </summary>
        /// <param name="code"></param>
        /// <param name="station"></param>
        /// <returns></returns>
        private bool CodeIsSave(string code, string station)
        {
            if (station.Equals(SystemConstant.OP10L) || station.Equals(SystemConstant.OP10R))
            {
                return false;
            }

            if (station.Contains("NG"))
            {
                
                return false;
            }

            List<PartProcess> partProcesses = orderDao.QueryProcessFromCodeAndStation(code, station);

            List<PartProcess> partProcesses1 = partProcesses.Where(x => x.EndTime.Year == 1900).ToList();

            if (partProcesses.Count != partProcesses1.Count)
            {
                return true;
            }

            return false;

            //return orderDao.CodeIsSave(code, station);
        }

        /// <summary>
        /// 检测是否存在跳工序
        /// </summary>
        /// <param name="code"></param>
        /// <param name="station"></param>
        /// <returns></returns>
        private bool OperationIsOk(string code, string station, string operationId)
        {
            string lastStation = MappingTable.GetLastStation(station);

            if (string.IsNullOrEmpty(lastStation))
                return false;

            List<string> list = lastStation.Split(',').ToList();

            PartProcess partProcess = null;

            foreach (var lStation in list)
            {
                partProcess = orderDao.GetStationData(code, lStation);

                if (partProcess != null)
                    break;
            }

            if (partProcess == null)
            {
                Tools.ProduceLogTextError($"这个件[{code}]在[{station}]检测到[{lastStation}]无过站数据，需人工校验");

                /*// 偷偷增补
                orderDao.SaveStationData(code, lastStation, operationId);*/

                // 无数据
                return true;
            }
            else if (Tools.IsDateTimeValid(partProcess.StartTime) && !Tools.IsDateTimeValid(partProcess.EndTime))
            {
                // 无进有出，默认补齐
               /* partProcess.StartTime = partProcess.EndTime.AddMinutes(-1);

                orderDao.UpDateStationStartTime(partProcess, operationId);*/

                Tools.ProduceLogTextError($"这个件[{code}]在[{station}]补齐了一条无进有出数据，开始时间[{partProcess.StartTime}]，追溯码[{code}]");

                return true;
            }
            else if (!Tools.IsDateTimeValid(partProcess.StartTime) && Tools.IsDateTimeValid(partProcess.EndTime))
            {
                Tools.ProduceLogText($"这个件[{code}]在[{station}]检测到[{lastStation}]有进无出，需人工校验");

                /*partProcess.EndTime = partProcess.StartTime.AddMinutes(1);

                orderDao.UpDateStationEndTime(partProcess, operationId);*/

                // 有进无出
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 判断时间是否为空或者为最小值
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        private bool DateTimeIsNullOrEmpty(DateTime dateTime)
        {
            if (dateTime == null || dateTime == DateTime.MinValue)
                return true;

            return false;
        }

        /*/// <summary>
        /// 检测重码
        /// </summary>
        /// <param name="code"></param>
        /// <param name="station"></param>
        /// <returns></returns>
        private bool CodeIsSave(string code, string station)
        {
            bool isSave = orderDao.CodeIsSave(code, station);

            // 判断当前是否是NG回流后的第一个工位
            if (MappingTable.GetNgStation(station))
            {
                if (isSave)
                {
                    // 存在重码，检测是否有NG入站记录
                    bool ngIsSave = orderDao.NgStationIsSave(code, station, "2");

                    return !ngIsSave;
                }

                return isSave;
            }
            else
            {
                return isSave;
            }
        }*/

        /// <summary>
        /// 产量校验
        /// </summary>
        /// <param name="station"></param>
        /// <returns></returns>
        private bool OrderProductionIsOk(string station)
        {
            if (station.Equals(SystemConstant.OP10L) || station.Equals(SystemConstant.OP10R))
            {
                OrderSingletonModel orderSingletonModel = OrderSingleton.GetOrderId(station);

                if (orderSingletonModel == null)
                    return false;

                if (orderSingletonModel.ProducessNumNow >= orderSingletonModel.ProducessNum)
                    return true;
            }
           

            return false;
        }

        #region 私有方法
        /// <summary>
        /// 格式校验
        /// </summary>
        /// <param name="code"></param>
        private bool CodeIsOk(string code,string station)
        {
            // 正则表达式1：匹配第一种格式 "LAC-51010298 5FK 2A230631 X200001 230831 00001"
            /*  Regex regex1 = new Regex(@"^LAC-\d{8} [A-Z0-9]{3} \d{1}[A-Z]{1}\d{6} [A-Z0-9]{1}\d{6} \d{6} \d{5}$");

              // 正则表达式2：匹配第二种格式 "LAC-56010050 01 5FK 2A230631 X200001 230831 A 00001"
              Regex regex2 = new Regex(@"^LAC-\d{8} \d{2} [A-Z0-9]{3} \d{1}[A-Z]{1}\d{6} [A-Z0-9]{1}\d{6} \d{6} [A-Z] \d{5}$");

              // 正则表达式3：匹配第三种格式 "LAC-84001059 08 240705 A 00001"
              Regex regex3 = new Regex(@"^LAC-\d{8} \d{2} \d{6} [A-Z] \d{5}$");

              // 正则表达式4：匹配第四种格式 "LAC-56010050-1 01 5FK 2A230631 X200001 230831 A 00001"
              Regex regex4 = new Regex(@"^LAC-\d{8}-\d{1} \d{2} [A-Z0-9]{3} \d{1}[A-Z]{1}\d{6} [A-Z0-9]{1}\d{6} \d{6} [A-Z] \d{5}$");*/


            // 正则表达式1：匹配第一种格式 "LAC-51010298 5FK 2A230631 X200001 230831 00001"
            // 修改后：5FK后面有4个字段，每个字段的字符数量保持不变，但不限制内容
            Regex regex1 = new Regex(@"^LAC-\d{8} [A-Z0-9]{3} .{8} .{7} .{6} .{5}$");

            // 正则表达式2：匹配第二种格式 "LAC-56010050 01 5FK 2A230631 X200001 230831 A 00001"
            // 修改后：5FK后面有5个字段，保持字符数量但不限制内容
            Regex regex2 = new Regex(@"^LAC-\d{8} \d{2} [A-Z0-9]{3} .{8} .{7} .{6} .{1} .{5}$");

            // 正则表达式3：匹配第三种格式 "LAC-84001059 08 240705 A 00001"
            // 这个格式中没有"5FK"部分，但5FK位置对应的是日期字段，修改为：
            Regex regex3 = new Regex(@"^LAC-\d{8} \d{2} .{6} .{1} .{5}$");

            // 正则表达式4：匹配第四种格式 "LAC-56010050-1 01 5FK 2A230631 X200001 230831 A 00001"
            // 修改后：5FK后面有5个字段，保持字符数量但不限制内容
            Regex regex4 = new Regex(@"^LAC-\d{8}-\d{1} \d{2} [A-Z0-9]{3} .{8} .{7} .{6} .{1} .{5}$");

            bool a = regex1.IsMatch(code);
            bool b = regex2.IsMatch(code);
            bool c = regex3.IsMatch(code);
            bool d = regex4.IsMatch(code);

            if (station.Equals(SystemConstant.OP10L) || station.Equals(SystemConstant.OP10R))
            {
                return false;
            }
            else
            {
                if (!(a || b || c || d))
                {
                    return true;
                }
                return false;
            }
            
       
        }
        #endregion
    }
}
